package com.sunchen.asc.service.item.server;

import com.sunchen.asc.service.common.ResultResponse;
import com.sunchen.asc.service.common.ResultUtil;
import com.sunchen.asc.service.item.api.ItemService;
import com.sunchen.asc.service.item.domain.*;
import com.sunchen.asc.service.item.domain.Process;
import com.sunchen.asc.service.item.repository.*;
import com.sunchen.asc.service.item.vo.*;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@DubboService(retries = 0)
public class ItemServiceImpl implements ItemService {

    @Autowired
    ItemRepository itemRepository;
    @Autowired
    ItemInfoRepository itemInfoRepository;
    @Autowired
    ProcessRepository processRepository;
    @Autowired
    BasisRepository basisRepository;
    @Autowired
    ChargeRepository chargeRepository;
    @Autowired
    MaterialRepository materialRepository;
    @Autowired
    ResultRepository resultRepository;

    public ResultResponse create(AllItemVo allItemVo) {

        Item item = new Item();
        BeanUtils.copyProperties(item,allItemVo.getItemVo());
        item.setDeleteFlag(0);
        item.setChildCount(0);
        item.setStatus(1);
        item.setItemMark(0);
        //item.setCreateUser();
        item = itemRepository.save(item);

        if (item.getParentId() != 0){
            Item father = itemRepository.getOne(item.getParentId());
            father.setChildCount(father.getChildCount()+1);
            itemRepository.save(father);
        }

        if (item.getHasChild() == 1){
            return ResultUtil.success("1");
        }

        Long itemId = item.getId();

        ItemInfo itemInfo = new ItemInfo();
        BeanUtils.copyProperties(itemInfo,allItemVo.getItemInfoVo());
        itemInfo.setItemId(itemId);
        //itemInfo.setCreateUser();
        itemInfoRepository.save(itemInfo);

        List<Process> processes = allItemVo.getProcessVos().stream().map(processVo -> {
            Process p = new Process();
            BeanUtils.copyProperties(p,processVo);
            p.setItemId(itemId);
            return p;
        }).collect(Collectors.toList());
        processRepository.saveAll(processes);

        List<Material> materials = allItemVo.getMaterialVos().stream().map(materialVo -> {
            Material m = new Material();
            BeanUtils.copyProperties(m,materialVo);
            m.setItemId(itemId);
            return m;
        }).collect(Collectors.toList());
        materialRepository.saveAll(materials);

        List<Result> results = allItemVo.getResultVos().stream().map(resultVo -> {
            Result r = new Result();
            BeanUtils.copyProperties(r,resultVo);
            r.setItemId(itemId);
            return r;
        }).collect(Collectors.toList());
        resultRepository.saveAll(results);

        List<Basis> bases = allItemVo.getBasisVos().stream().map(basisVo -> {
            Basis b = new Basis();
            BeanUtils.copyProperties(b,basisVo);
            b.setItemId(itemId);
            return b;
        }).collect(Collectors.toList());
        basisRepository.saveAll(bases);

        if (item.getChargeFlag() == 1){
            List<Charge> charges = allItemVo.getChargeVos().stream().map(chargeVo -> {
                Charge c = new Charge();
                BeanUtils.copyProperties(c,chargeVo);
                c.setItemId(itemId);
                return c;
            }).collect(Collectors.toList());
            chargeRepository.saveAll(charges);
        }

        return ResultUtil.success("1");
    }

    public ResultResponse edit(AllItemVo allItemVo) {

        Long itemId = allItemVo.getItemVo().getId();

        Item item = itemRepository.getOne(itemId);
        if (item.getHasChild() == 1){
            item.setCode(allItemVo.getItemVo().getCode());
            item.setName(allItemVo.getItemVo().getName());
            item.setWorkCode(allItemVo.getItemVo().getWorkCode());
            item.setLevel(allItemVo.getItemVo().getLevel());
            item.setBasis(allItemVo.getItemVo().getBasis());
            item.setPower(allItemVo.getItemVo().getPower());
            item.setAcceptDeptId(allItemVo.getItemVo().getAcceptDeptId());
            item.setAcceptDeptName(allItemVo.getItemVo().getAcceptDeptName());
            item.setItemType(allItemVo.getItemVo().getItemType());
            //item.setUpdateUser();
            itemRepository.save(item);
            return ResultUtil.success("1");
        }

        item.setCode(allItemVo.getItemVo().getCode());
        item.setName(allItemVo.getItemVo().getName());
        item.setAcceptDeptId(allItemVo.getItemVo().getAcceptDeptId());
        item.setAcceptDeptName(allItemVo.getItemVo().getAcceptDeptName());
        item.setToFace(allItemVo.getItemVo().getToFace());
        item.setChargeFlag(allItemVo.getItemVo().getChargeFlag());
        item.setServiceObject(allItemVo.getItemVo().getServiceObject());
        item.setLifeCycle(allItemVo.getItemVo().getLifeCycle());
        item.setItemType(allItemVo.getItemVo().getItemType());
        item.setAddressId(allItemVo.getItemVo().getAddressId());
        //item.setUpdateUser();
        itemRepository.save(item);

        // TODO: 2021/1/4 挑选需要改变的值
        ItemInfo itemInfo = itemInfoRepository.getOne(allItemVo.getItemInfoVo().getId());
        itemInfo.setBusinessCode(allItemVo.getItemInfoVo().getBusinessCode());
        itemInfo.setDeptName(allItemVo.getItemInfoVo().getDeptName());
        itemInfo.setWorkTime(allItemVo.getItemInfoVo().getWorkTime());
        itemInfo.setWorkPlace(allItemVo.getItemInfoVo().getWorkPlace());
        itemInfo.setPowerSource(allItemVo.getItemInfoVo().getPowerSource());
        itemInfo.setOnlinePay(allItemVo.getItemInfoVo().getOnlinePay());
        itemInfo.setOrgName(allItemVo.getItemInfoVo().getOrgName());
        itemInfo.setOrgDecide(allItemVo.getItemInfoVo().getOrgDecide());
        itemInfo.setOrgJoint(allItemVo.getItemInfoVo().getOrgJoint());
        itemInfo.setOrgProperty(allItemVo.getItemInfoVo().getOrgProperty());
        itemInfo.setTypeInHall(allItemVo.getItemInfoVo().getTypeInHall());
        itemInfo.setProcessTel(allItemVo.getItemInfoVo().getProcessTel());
        itemInfo.setAuthLevel(allItemVo.getItemInfoVo().getAuthLevel());
        itemInfo.setRunSystem(allItemVo.getItemInfoVo().getRunSystem());
        itemInfo.setDelivery(allItemVo.getItemInfoVo().getDelivery());
        itemInfo.setHandleType(allItemVo.getItemInfoVo().getHandleType());
        itemInfo.setIsReserve(allItemVo.getItemInfoVo().getIsReserve());
        itemInfo.setHandleForm(allItemVo.getItemInfoVo().getHandleForm());
        itemInfo.setZj(allItemVo.getItemInfoVo().getZj());
        itemInfo.setLimitNumber(allItemVo.getItemInfoVo().getLimitNumber());
        itemInfo.setCrossScope(allItemVo.getItemInfoVo().getCrossScope());
        itemInfo.setExerciseContent(allItemVo.getItemInfoVo().getExerciseContent());
        itemInfo.setAuthorityDivision(allItemVo.getItemInfoVo().getAuthorityDivision());
        itemInfo.setProcedure(allItemVo.getItemInfoVo().getProcedure());
        itemInfo.setReason(allItemVo.getItemInfoVo().getReason());
        itemInfo.setApplyCondition(allItemVo.getItemInfoVo().getApplyCondition());
        itemInfo.setAgreeType(allItemVo.getItemInfoVo().getAgreeType());
        itemInfo.setApplyTimes(allItemVo.getItemInfoVo().getApplyTimes());
        itemInfo.setLawTime(allItemVo.getItemInfoVo().getLawTime());
        itemInfo.setAgreeTime(allItemVo.getItemInfoVo().getAgreeTime());
        itemInfo.setAgreeTimeReason(allItemVo.getItemInfoVo().getAgreeTimeReason());
        itemInfo.setAdvisoryPhone(allItemVo.getItemInfoVo().getAdvisoryPhone());
        itemInfo.setAdvisoryAddress(allItemVo.getItemInfoVo().getAdvisoryAddress());
        itemInfo.setComplainPhone(allItemVo.getItemInfoVo().getComplainPhone());
        itemInfo.setComplainAddress(allItemVo.getItemInfoVo().getComplainAddress());
        itemInfo.setProblem(allItemVo.getItemInfoVo().getProblem());
        itemInfo.setAssess(allItemVo.getItemInfoVo().getAssess());
        //itemInfo.setUpdateUser();
        itemInfoRepository.save(itemInfo);

        // TODO: 2021/1/4 附件的删除
        processRepository.deleteAllByItemId(itemId);
        materialRepository.deleteAllByItemId(itemId);
        resultRepository.deleteAllByItemId(itemId);
        basisRepository.deleteAllByItemId(itemId);
        chargeRepository.deleteAllByItemId(itemId);

        List<Process> processes = allItemVo.getProcessVos().stream().map(processVo -> {
            Process p = new Process();
            BeanUtils.copyProperties(p,processVo);
            p.setItemId(itemId);
            return p;
        }).collect(Collectors.toList());
        processRepository.saveAll(processes);

        List<Material> materials = allItemVo.getMaterialVos().stream().map(materialVo -> {
            Material m = new Material();
            BeanUtils.copyProperties(m,materialVo);
            m.setItemId(itemId);
            return m;
        }).collect(Collectors.toList());
        materialRepository.saveAll(materials);

        List<Result> results = allItemVo.getResultVos().stream().map(resultVo -> {
            Result r = new Result();
            BeanUtils.copyProperties(r,resultVo);
            r.setItemId(itemId);
            return r;
        }).collect(Collectors.toList());
        resultRepository.saveAll(results);

        List<Basis> bases = allItemVo.getBasisVos().stream().map(basisVo -> {
            Basis b = new Basis();
            BeanUtils.copyProperties(b,basisVo);
            b.setItemId(itemId);
            return b;
        }).collect(Collectors.toList());
        basisRepository.saveAll(bases);

        if (item.getChargeFlag() == 1){
            List<Charge> charges = allItemVo.getChargeVos().stream().map(chargeVo -> {
                Charge c = new Charge();
                BeanUtils.copyProperties(c,chargeVo);
                c.setItemId(itemId);
                return c;
            }).collect(Collectors.toList());
            chargeRepository.saveAll(charges);
        }

        return ResultUtil.success("1");
    }

    public ResultResponse delete(Long id) {

        Item item = itemRepository.getOne(id);
        if (item.getHasChild() == 1 && item.getChildCount() > 0){
            return ResultUtil.failed("存在子事项，无法删除");
        }
        item.setDeleteFlag(1);
        item.setDeleteTime(new Timestamp(System.currentTimeMillis()));
        //item.setDeleteUser();
        item.setStatus(2);
        itemRepository.save(item);

        if (item.getParentId() != 0){
            Item father = itemRepository.getOne(item.getParentId());
            father.setChildCount(father.getChildCount() - 1);
        }
        return ResultUtil.success("1");
    }

    public ResultResponse detail(Long id) {

        ItemVo itemVo = itemRepository.getVo(id);
        Long itemId = itemVo.getId();
        ItemInfoVo itemInfoVo = itemInfoRepository.getVoByItemId(itemId);
        List<ProcessVo> processVos = processRepository.getVosByItemId(itemId);
        List<MaterialVo> materialVos = materialRepository.getVosByItemId(itemId);
        List<ResultVo> resultVos = resultRepository.getVosByItemId(itemId);
        List<BasisVo> basisVos = basisRepository.getVosByItemId(itemId);
        List<ChargeVo> chargeVos = null;
        if (itemVo.getChargeFlag() == 1){
            chargeVos = chargeRepository.getVosByItemId(itemId);
        }
        AllItemVo allItemVo = new AllItemVo();
        allItemVo.setItemVo(itemVo);
        allItemVo.setItemInfoVo(itemInfoVo);
        allItemVo.setProcessVos(processVos);
        allItemVo.setMaterialVos(materialVos);
        allItemVo.setResultVos(resultVos);
        allItemVo.setBasisVos(basisVos);
        allItemVo.setChargeVos(chargeVos);

        return ResultUtil.success(allItemVo);
    }

    public ResultResponse fatherDetail(Long id) {

        ItemVo father = itemRepository.getVo(id);
        List<ItemVo> sons = itemRepository.getSonVo(id);
        FatherDetailVo fatherDetailVo = new FatherDetailVo();
        fatherDetailVo.setFather(father);
        fatherDetailVo.setSons(sons);
        return ResultUtil.success(fatherDetailVo);
    }

    public ResultResponse mark(Long id, Integer itemMark) {

        Item item = itemRepository.getOne(id);
        item.setItemMark(itemMark);
        //item.setUpdateUser();
        itemRepository.save(item);
        return ResultUtil.success("1");
    }

    public ResultResponse sonList(Long id) {

        List<ItemVo> voList = itemRepository.getSonVo(id);
        return ResultUtil.success(voList);
    }

    public ResultResponse release(Long id) {

        Item item = itemRepository.getOne(id);
        item.setStatus(1);
        itemRepository.save(item);
        return ResultUtil.success("1");
    }

    public ResultResponse releaseCancel(Long id) {

        Item item = itemRepository.getOne(id);
        if (item.getHasChild() == 1 && item.getChildCount() > 0){
            return ResultUtil.failed("存在子事项，无法取消");
        }
        item.setStatus(2);
        itemRepository.save(item);
        return ResultUtil.success("1");
    }

    public ResultResponse list(String name, Long titleId, Long addressId, Long acceptDeptId, String itemType, Integer onlineFlag, String serviceObject, String lifeCycle, Integer titleType, Pageable pageable) {

        Page<Item> resultPage = null;
        Specification specification = new Specification<Item>() {
            @Override
            public Predicate toPredicate(Root<Item> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {

                List<Predicate> predicates = new ArrayList<>();
                //显示：未删除的、已发布的、父级id为0的（树形中第一级的）
                Predicate delete = criteriaBuilder.equal(root.get("deleteFlag") , 0);
                predicates.add(delete);
                Predicate status = criteriaBuilder.equal(root.get("status") , 1);
                predicates.add(status);
                Predicate pid = criteriaBuilder.equal(root.get("parentId") , 0L);
                predicates.add(pid);

                if (titleType != null){
                    Predicate p = criteriaBuilder.equal(root.get("titleType") , titleType);
                    predicates.add(p);
                }

                if (name != null && name.length() > 0){
                    Predicate p = criteriaBuilder.like(root.get("name") , "%"+name+"%");
                    predicates.add(p);
                }
                if (titleId != null){
                    Predicate p = criteriaBuilder.equal(root.get("titleId") , titleId);
                    predicates.add(p);
                }
                if (addressId != null){
                    Predicate p = criteriaBuilder.equal(root.get("addressId") , addressId);
                    predicates.add(p);
                }
                if (acceptDeptId != null){
                    Predicate p = criteriaBuilder.equal(root.get("acceptDeptId") , acceptDeptId);
                    predicates.add(p);
                }
                if (itemType != null && itemType.length() > 0){
                    Predicate p = criteriaBuilder.like(root.get("itemType") , "%"+itemType+"%");
                    predicates.add(p);
                }
                if (onlineFlag != null){
                    Predicate p = criteriaBuilder.equal(root.get("onlineFlag") , onlineFlag);
                    predicates.add(p);
                }
                if (serviceObject != null && serviceObject.length() > 0){
                    Predicate p = criteriaBuilder.like(root.get("serviceObject") , "%"+serviceObject+"%");
                    predicates.add(p);
                }
                if (lifeCycle != null && lifeCycle.length() > 0){
                    Predicate p = criteriaBuilder.like(root.get("lifeCycle") , "%"+lifeCycle+"%");
                    predicates.add(p);
                }
                Predicate[] pre = new Predicate[predicates.size()];
                return criteriaBuilder.and(predicates.toArray(pre));
            }
        };
        resultPage = itemRepository.findAll(specification,pageable);
        List<ItemVo> voList = resultPage.getContent().stream().map(item -> {
            ItemVo vo = new ItemVo();
            BeanUtils.copyProperties(vo,item);
            return vo;
        }).collect(Collectors.toList());

        Page<ItemVo> vos = new PageImpl<>(voList, resultPage.getPageable(), resultPage.getTotalElements());
        return ResultUtil.success(vos);
    }


}
